#include <iostream>
#include <stdio.h>
#include <assert.h>

namespace zz
{
	template<class type>
	class Vector
	{
	public:

		typedef type* iterator;
		typedef const type* const_iterator;
		Vector()
		{
			_begin = nullptr;
			_end = nullptr;
			_end_storage = nullptr;
		}

		Vector(const Vector<type>& v)
		{
			_begin = new type[v.capacity()];
			//memcpy(_begin, v._begin, v.size());
			iterator it1 = _begin;
			iterator it2 = v._begin;
			while (it2 != v._end)
			{
				*it1 = *it2;
				it1++;
				it2++;
			}
			_end = _begin + v.size();
			_end_storage = _begin + v.capacity();

			//reserve(v.capacity());
			//for (const auto &e : v)
			//{
			//	Pushback(e);
			//}
		}

		~Vector()
		{
			if (_begin)
			{
				delete[] _begin;
				_begin = nullptr;
				_end = nullptr;
				_end_storage = nullptr;
			}
		}

		const_iterator end_storage()const
		{
			return _end_storage;
		}

		const_iterator end()const
		{
			return _end;
		}

		const_iterator begin()const
		{
			return _begin();
		}

		void Insert(size_t pos, type val)
		{
			assert(pos <= size());
			if (capacity() == size())
			{
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}
			for (size_t i = size()-1; i >= pos; i--)
			{
				_begin[i+1] = _begin[i];
			}
			_begin[pos] = val;
			_end++;
		}

		type Erase(size_t pos)
		{
			assert(pos <= size());
			type del_val = _begin[pos];
			for (size_t i = pos+1; i < size(); i++)
			{
				_begin[i-1] = _begin[i];
			}
			_end--;
			return del_val;
		}

		iterator Erase(iterator pos)
		{
			assert(pos < _end);
			assert(pos >= _begin);
			iterator it = pos+1;
			while (it != _end)
			{
				*(it - 1) = *it;
				it++;
			}
			_end--;
			return pos;
		}

		size_t capacity()const
		{
			return _end_storage - _begin;
		}

		size_t size()const
		{
			return _end - _begin;
		}

		void Pushback(int x)
		{
			if (capacity() == size())
			{
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}

			*_end = x;
			_end++;
		}

		void reserve(size_t n)
		{
			if (n > size())
			{
				type* tmp = new type[n];
				if (tmp)
				{
					size_t sz = size();
					memcpy(tmp, _begin, sz*sizeof(type));
					
					delete[] _begin;
					_begin = tmp;
					_end = _begin + sz;
					_end_storage = _begin + n;
				}
			}
		}

		Vector<type>& operator=(Vector<type> v)
		{
			swap(v);
			return *this;
		}

		void Swap(Vector<type>& v)
		{
			std::swap(v._begin, _begin);
			std::swap(v._end, _end);
			std::swap(v._end_storage, _end_storage);
		}

		Vector<type>& operator[](size_t pos)
		{
			assert(pos < size());
			return _begin[pos];
		}

		const Vector<type>& operator[](size_t pos)const
		{
			assert(pos < size());
			return _begin[pos];
		}

		void Print()
		{
			iterator it=_begin;
			while (it != _end)
			{
				std::cout << *it<<' ';
				it++;
			}
			std::cout << std::endl;
		}

	private:
		iterator _begin;
		iterator _end;
		iterator _end_storage;

	};

	//void Print(const Vector<int>& v)
	//{
	//	for (const auto& e : v)
	//	{
	//		std::cout << e << ' ';
	//	}
	//	std::cout << std::endl;
	//}

	void Test1()
	{
		Vector<int> v;
		v.Pushback(1);
		v.Pushback(2);
		v.Pushback(3);
		v.Pushback(3);
		v.Pushback(3);
		v.Pushback(3);
		v.Pushback(3);
		v.Pushback(3);
		v.Pushback(3);
		v.Print();

		Vector<int> v2(v);
		v.Print();

		v2.Insert(2, 9);
		v2.Print();

		v2.Insert(1, 0);	
		v2.Print();
		v2.Insert(7, 23);
		v2.Insert(7, 23);
		v2.Insert(7, 23);
		v2.Insert(7, 23);
		v2.Insert(7, 23);
		v2.Insert(7, 23);
		v2.Print();
		v2.Erase(1);
		v2.Print();
		v2.Erase(1);
		v2.Print();
		v2.Erase(1);
		v2.Print();
		v2.Erase(1);
		v2.Print();
		v2.Erase(1);
		v2.Print();
		v2.Erase(1);
		v2.Print();
		v2.Erase(1);
		v2.Print();
		v2.Erase(1);
		v2.Print();
	}
}

int main()
{
	zz::Test1();

	return 0;
}